<?php
/*
	Author: coooold@newsmth
	Date:	2013.08.14
	Des:	For any purpose!
*/

/*
 * MongoConn Mongo连接类，负责增删改查等
 */
class MongoConn{
	static protected $conn = null;
	static public function getConn(){
		if(self::$conn == null)
		{
			self::$conn = new MongoClient(_MONGODB_HOST); // 连接
		}
		return self::$conn;
	}
	
	static public function save($db, $col, $data, $option = array())
	{
		$m = self::getConn();
		$db = $m->selectDB($db);
		$col = $db->selectCollection($col);
		$col->save($data, $option);
	}
	
	static public function insert($db, $col, $data, $option = array())
	{
		$m = self::getConn();
		$db = $m->selectDB($db);
		$col = $db->selectCollection($col);
		$col->insert($data, $option);
	}
	
	static public function find($db, $col, $query = array(), $option = array())
	{
		$m = self::getConn();
		$db = $m->selectDB($db);
		$col = $db->selectCollection($col);
		return $col->find($query, $option);
	}
	
	static public function findOne($db, $col, $query = array(), $option = array())
	{
		$m = self::getConn();
		$db = $m->selectDB($db);
		$col = $db->selectCollection($col);
		return $col->findOne($query, $option);
	}
	
	static public function remove($db, $col, $query = array(), $option = array())
	{
		$m = self::getConn();
		$db = $m->selectDB($db);
		$col = $db->selectCollection($col);
		$col->remove($query, $option);
	}
	
	static public function count($db, $col, $query)
	{
		$m = self::getConn();
		$db = $m->selectDB($db);
		$col = $db->selectCollection($col);
		return $col->count($query);
	}
}

/*
 * 模型类，有创建、修改、查找、删除等功能
 */
class MongoBean{
	protected static $dbName = 'mongo';
	protected static $collectionName = 'col';
	
	
	static public function create()
	{
		$bean = new static();
		$bean->setCreated();
		
		return $bean;
	}
	
	static public function getFields() {
		$ref = new ReflectionClass ( get_called_class () );
		$fieldsRef = $ref->getProperties ( ReflectionProperty::IS_PUBLIC );
		$fields = array ();
		foreach ( $fieldsRef as $item ) {
			$fields [] = $item->name;
		}
		
		$fields = array_diff($fields, array('_id'));
		return $fields;
	}
	
	static public function findOneById($id)
	{
		if($id instanceof MongoId)return static::findOne(array('_id'=>$id));
		else return static::findOne(array('_id'=>new MongoId($id)));
	}
	
	static public function findOne($query = array())
	{
		$db = static::$dbName;
		$col = static::$collectionName;
		
		$data = MongoConn::findOne($db, $col, $query);

		if(!$data)return null;
		return new static($data);
	}
	
	static public function find($query = array(), $sort = null, $limit = null)
	{
		$db = static::$dbName;
		$col = static::$collectionName;
		
		$data = MongoConn::find($db, $col, $query);
		
		if($sort){
			$data = $data->sort($sort);
		}
		
		if($limit){
			$data = $data->limit($limit);
		}
		
		$result = array();
		foreach($data as $row)
		{
			$result[] = new static($row);
		}

		return $result;
	}
	
	static public function count($query = array())
	{
		$db = static::$dbName;
		$col = static::$collectionName;
		
		return MongoConn::count($db, $col, $query);
	}
	
	
	///////////////////////////////////////
	
	protected function __construct($data = array()) {
		if(array_key_exists('_id', $data))$this->_id = $data['_id'];
		
		$fields = static::getFields ();

		foreach ( $fields as $field ) {
			if (array_key_exists ( $field, $data )) {
				$this->$field = $data [$field];
			}
		}
	}
	
	protected $_is_created = false;
	protected $_is_deleted = false;
	protected $_is_modified = false;
	protected $_is_saved = false;
	
	protected function setCreated(){
		$this->_is_created = true;
	}
	
	
	public function remove() {
		$this->_is_deleted = true;
	}
	
	public function save() {
		if ($this->_is_saved)
			throw new Exception ( '已经保存' );
		
		$fields = static::getFields ();
		$db = static::$dbName;
		$col = static::$collectionName;
		
		if ($this->_is_created) {
			$data = array();
			foreach ( $fields as $field ) {
				$data[$field] = $this->{$field};
			}
			
			MongoConn::insert($db, $col, $data);
			
			$this->_id = $data['_id'];
		} elseif ($this->_is_deleted) {
			MongoConn::remove($db, $col, array('_id'=>$this->_id), array('justOne'=>true));
		} else {
			$data = array();
			foreach ( $fields as $field ) {
				$data[$field] = $this->{$field};
			}
			$data['_id'] = $this->_id;
			
			MongoConn::save($db, $col, $data);
		}
		
		$this->_is_saved = true;
	}
	
	
	///////////////////
	public $_id;
}